package com.ruoyi.system.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.mapper.DatingMatchMapper;
import com.ruoyi.system.mapper.DatingMemberMapper;
import com.ruoyi.system.domain.DatingMatch;
import com.ruoyi.system.domain.DatingMember;
import com.ruoyi.system.service.IDatingMatchService;

/**
 * 婚恋匹配记录Service业务层处理
 *
 * @author ruoyi
 * @date 2024-01-15
 */
@Service
public class DatingMatchServiceImpl implements IDatingMatchService
{
    @Autowired
    private DatingMatchMapper datingMatchMapper;

    @Autowired
    private DatingMemberMapper datingMemberMapper;

    /**
     * 查询婚恋匹配记录
     *
     * @param matchId 婚恋匹配记录主键
     * @return 婚恋匹配记录
     */
    @Override
    public DatingMatch selectDatingMatchByMatchId(Long matchId)
    {
        return datingMatchMapper.selectById(matchId);
    }

    /**
     * 查询婚恋匹配记录列表
     *
     * @param datingMatch 婚恋匹配记录
     * @return 婚恋匹配记录
     */
    @Override
    public List<DatingMatch> selectDatingMatchList(DatingMatch datingMatch)
    {
        return datingMatchMapper.selectDatingMatchList(datingMatch);
    }

    /**
     * 新增婚恋匹配记录
     *
     * @param datingMatch 婚恋匹配记录
     * @return 结果
     */
    @Override
    public int insertDatingMatch(DatingMatch datingMatch)
    {
        // 自动填充字段：createTime、createBy、updateTime、updateBy、delFlag
        return datingMatchMapper.insert(datingMatch);
    }

    /**
     * 修改婚恋匹配记录
     *
     * @param datingMatch 婚恋匹配记录
     * @return 结果
     */
    @Override
    public int updateDatingMatch(DatingMatch datingMatch)
    {
        // 自动填充字段：updateTime、updateBy
        return datingMatchMapper.updateById(datingMatch);
    }

    /**
     * 批量删除婚恋匹配记录
     *
     * @param matchIds 需要删除的婚恋匹配记录主键
     * @return 结果
     */
    @Override
    public int deleteDatingMatchByMatchIds(Long[] matchIds)
    {
        return datingMatchMapper.deleteBatchIds(Arrays.asList(matchIds));
    }

    /**
     * 删除婚恋匹配记录信息
     *
     * @param matchId 婚恋匹配记录主键
     * @return 结果
     */
    @Override
    public int deleteDatingMatchByMatchId(Long matchId)
    {
        return datingMatchMapper.deleteById(matchId);
    }

    /**
     * 自动匹配算法 - 为指定人员寻找最佳匹配
     *
     * @param memberId 人员ID
     * @param maxCount 最大匹配数量
     * @return 匹配结果列表
     */
    @Override
    public List<DatingMatch> autoMatch(Long memberId, int maxCount)
    {
        // 1. 获取目标人员信息
        DatingMember targetMember = datingMemberMapper.selectById(memberId);
        if (targetMember == null) {
            return new ArrayList<>();
        }

        // 2. 获取符合基本条件的候选人员
        List<DatingMember> candidates = datingMemberMapper.selectMatchableMemberList(targetMember);

        // 3. 过滤掉已经匹配过的人员
        candidates = candidates.stream()
            .filter(candidate -> datingMatchMapper.checkExistMatch(memberId, candidate.getMemberId()) == 0)
            .collect(Collectors.toList());

        // 4. 计算匹配得分并排序
        List<MatchCandidate> scoredCandidates = new ArrayList<>();
        for (DatingMember candidate : candidates) {
            double score = calculateMatchScore(targetMember, candidate);
            if (score >= 60.0) { // 只保留得分60分以上的候选人
                scoredCandidates.add(new MatchCandidate(candidate, score));
            }
        }

        // 5. 按得分降序排序，取前maxCount个
        scoredCandidates.sort((a, b) -> Double.compare(b.getScore(), a.getScore()));

        // 6. 创建匹配记录
        List<DatingMatch> matches = new ArrayList<>();
        int count = Math.min(maxCount, scoredCandidates.size());

        for (int i = 0; i < count; i++) {
            MatchCandidate candidate = scoredCandidates.get(i);
            DatingMatch match = createAutoMatch(targetMember, candidate.getMember(), candidate.getScore());
            matches.add(match);
        }

        return matches;
    }

    /**
     * 计算两个人员的匹配得分
     * 综合考虑年龄、身高、学历、收入、地理位置、兴趣爱好等因素
     *
     * @param memberA 人员A
     * @param memberB 人员B
     * @return 匹配得分 (0-100)
     */
    @Override
    public double calculateMatchScore(DatingMember memberA, DatingMember memberB)
    {
        double totalScore = 0.0;
        double weightSum = 0.0;

        // 1. 年龄匹配度 (权重: 25%)
        double ageScore = calculateAgeCompatibility(memberA, memberB);
        totalScore += ageScore * 0.25;
        weightSum += 0.25;

        // 2. 身高匹配度 (权重: 15%)
        double heightScore = calculateHeightCompatibility(memberA, memberB);
        totalScore += heightScore * 0.15;
        weightSum += 0.15;

        // 3. 学历匹配度 (权重: 20%)
        double educationScore = calculateEducationCompatibility(memberA, memberB);
        totalScore += educationScore * 0.20;
        weightSum += 0.20;

        // 4. 收入匹配度 (权重: 20%)
        double incomeScore = calculateIncomeCompatibility(memberA, memberB);
        totalScore += incomeScore * 0.20;
        weightSum += 0.20;

        // 5. 地理位置匹配度 (权重: 10%)
        double locationScore = calculateLocationCompatibility(memberA, memberB);
        totalScore += locationScore * 0.10;
        weightSum += 0.10;

        // 6. 兴趣爱好匹配度 (权重: 10%)
        double hobbyScore = calculateHobbyCompatibility(memberA, memberB);
        totalScore += hobbyScore * 0.10;
        weightSum += 0.10;

        // 返回加权平均分
        return weightSum > 0 ? (totalScore / weightSum) * 100 : 0.0;
    }

    /**
     * 计算年龄匹配度
     */
    private double calculateAgeCompatibility(DatingMember memberA, DatingMember memberB)
    {
        if (memberA.getAge() == null || memberB.getAge() == null) {
            return 0.5; // 信息不完整时给中等分
        }

        // 检查B是否在A的期望年龄范围内，以及A是否在B的期望年龄范围内
        boolean aLikesB = (memberA.getMateAgeMin() == null || memberB.getAge() >= memberA.getMateAgeMin()) &&
                         (memberA.getMateAgeMax() == null || memberB.getAge() <= memberA.getMateAgeMax());

        boolean bLikesA = (memberB.getMateAgeMin() == null || memberA.getAge() >= memberB.getMateAgeMin()) &&
                         (memberB.getMateAgeMax() == null || memberA.getAge() <= memberB.getMateAgeMax());

        if (aLikesB && bLikesA) {
            return 1.0; // 双方都满意
        } else if (aLikesB || bLikesA) {
            return 0.7; // 单方满意
        } else {
            // 计算年龄差距的接受度
            int ageDiff = Math.abs(memberA.getAge().intValue() - memberB.getAge().intValue());
            if (ageDiff <= 3) return 0.6;
            if (ageDiff <= 5) return 0.4;
            if (ageDiff <= 8) return 0.2;
            return 0.1;
        }
    }

    /**
     * 计算身高匹配度
     */
    private double calculateHeightCompatibility(DatingMember memberA, DatingMember memberB)
    {
        if (memberA.getHeight() == null || memberB.getHeight() == null) {
            return 0.5;
        }

        // 检查身高是否在期望范围内
        boolean aLikesB = (memberA.getMateHeightMin() == null || memberB.getHeight() >= memberA.getMateHeightMin()) &&
                         (memberA.getMateHeightMax() == null || memberB.getHeight() <= memberA.getMateHeightMax());

        boolean bLikesA = (memberB.getMateHeightMin() == null || memberA.getHeight() >= memberB.getMateHeightMin()) &&
                         (memberB.getMateHeightMax() == null || memberA.getHeight() <= memberB.getMateHeightMax());

        if (aLikesB && bLikesA) {
            return 1.0;
        } else if (aLikesB || bLikesA) {
            return 0.7;
        } else {
            return 0.3;
        }
    }

    /**
     * 计算学历匹配度
     */
    private double calculateEducationCompatibility(DatingMember memberA, DatingMember memberB)
    {
        if (memberA.getEducation() == null || memberB.getEducation() == null) {
            return 0.5;
        }

        // 学历等级映射
        Map<String, Integer> educationLevel = new HashMap<>();
        educationLevel.put("初中", 1);
        educationLevel.put("高中", 2);
        educationLevel.put("大专", 3);
        educationLevel.put("本科", 4);
        educationLevel.put("硕士", 5);
        educationLevel.put("博士", 6);

        Integer levelA = educationLevel.get(memberA.getEducation());
        Integer levelB = educationLevel.get(memberB.getEducation());

        if (levelA == null || levelB == null) {
            return 0.5;
        }

        // 检查是否满足期望学历
        boolean aLikesB = memberA.getMateEducation() == null ||
                         memberA.getMateEducation().equals(memberB.getEducation()) ||
                         educationLevel.getOrDefault(memberA.getMateEducation(), 0) <= levelB;

        boolean bLikesA = memberB.getMateEducation() == null ||
                         memberB.getMateEducation().equals(memberA.getEducation()) ||
                         educationLevel.getOrDefault(memberB.getMateEducation(), 0) <= levelA;

        if (aLikesB && bLikesA) {
            return 1.0;
        } else if (aLikesB || bLikesA) {
            return 0.7;
        } else {
            // 根据学历差距计算分数
            int levelDiff = Math.abs(levelA - levelB);
            if (levelDiff == 0) return 0.8;
            if (levelDiff == 1) return 0.6;
            if (levelDiff == 2) return 0.4;
            return 0.2;
        }
    }

    /**
     * 计算收入匹配度
     */
    private double calculateIncomeCompatibility(DatingMember memberA, DatingMember memberB)
    {
        if (memberA.getMonthlyIncome() == null || memberB.getMonthlyIncome() == null) {
            return 0.5;
        }

        // 检查收入是否满足期望
        boolean aLikesB = memberA.getMateIncomeMin() == null ||
                         memberB.getMonthlyIncome().compareTo(memberA.getMateIncomeMin()) >= 0;

        boolean bLikesA = memberB.getMateIncomeMin() == null ||
                         memberA.getMonthlyIncome().compareTo(memberB.getMateIncomeMin()) >= 0;

        if (aLikesB && bLikesA) {
            return 1.0;
        } else if (aLikesB || bLikesA) {
            return 0.7;
        } else {
            return 0.3;
        }
    }

    /**
     * 计算地理位置匹配度
     */
    private double calculateLocationCompatibility(DatingMember memberA, DatingMember memberB)
    {
        if (memberA.getCity() == null || memberB.getCity() == null) {
            return 0.5;
        }

        // 同城最佳
        if (memberA.getCity().equals(memberB.getCity())) {
            return 1.0;
        }

        // 同省次之
        if (memberA.getProvince() != null && memberA.getProvince().equals(memberB.getProvince())) {
            return 0.7;
        }

        // 检查是否符合期望居住地
        boolean aLikesB = memberA.getMateLocation() == null ||
                         memberB.getCity().contains(memberA.getMateLocation()) ||
                         (memberB.getProvince() != null && memberB.getProvince().contains(memberA.getMateLocation()));

        boolean bLikesA = memberB.getMateLocation() == null ||
                         memberA.getCity().contains(memberB.getMateLocation()) ||
                         (memberA.getProvince() != null && memberA.getProvince().contains(memberB.getMateLocation()));

        if (aLikesB && bLikesA) {
            return 0.6;
        } else if (aLikesB || bLikesA) {
            return 0.4;
        } else {
            return 0.2;
        }
    }

    /**
     * 计算兴趣爱好匹配度
     */
    private double calculateHobbyCompatibility(DatingMember memberA, DatingMember memberB)
    {
        if (memberA.getHobbies() == null || memberB.getHobbies() == null) {
            return 0.5;
        }

        String[] hobbiesA = memberA.getHobbies().split("[,，、；;]");
        String[] hobbiesB = memberB.getHobbies().split("[,，、；;]");

        Set<String> setA = Arrays.stream(hobbiesA).map(String::trim).collect(Collectors.toSet());
        Set<String> setB = Arrays.stream(hobbiesB).map(String::trim).collect(Collectors.toSet());

        // 计算交集和并集
        Set<String> intersection = new HashSet<>(setA);
        intersection.retainAll(setB);

        Set<String> union = new HashSet<>(setA);
        union.addAll(setB);

        if (union.isEmpty()) {
            return 0.5;
        }

        // 使用Jaccard相似度
        double similarity = (double) intersection.size() / union.size();
        return similarity;
    }

    /**
     * 创建自动匹配记录
     */
    private DatingMatch createAutoMatch(DatingMember memberA, DatingMember memberB, double score)
    {
        DatingMatch match = new DatingMatch();
        match.setMemberIdA(memberA.getMemberId());
        match.setMemberIdB(memberB.getMemberId());
        match.setMatchScore(BigDecimal.valueOf(score).setScale(2, java.math.RoundingMode.HALF_UP));
        match.setMatchType("AUTO");
        match.setMatchStatus("MATCHED");
        match.setContactStatusA("PENDING");
        match.setContactStatusB("PENDING");
        match.setMatchResult("PENDING");
        // 自动填充字段：createTime、createBy、updateTime、updateBy、delFlag

        // 保存到数据库
        datingMatchMapper.insert(match);

        return match;
    }

    /**
     * 手动创建匹配
     */
    @Override
    public int createManualMatch(Long memberIdA, Long memberIdB, String remark)
    {
        // 检查是否已经存在匹配记录
        if (datingMatchMapper.checkExistMatch(memberIdA, memberIdB) > 0) {
            return 0; // 已存在匹配记录
        }

        // 获取人员信息计算匹配得分
        DatingMember memberA = datingMemberMapper.selectById(memberIdA);
        DatingMember memberB = datingMemberMapper.selectById(memberIdB);

        if (memberA == null || memberB == null) {
            return 0;
        }

        double score = calculateMatchScore(memberA, memberB);

        DatingMatch match = new DatingMatch();
        match.setMemberIdA(memberIdA);
        match.setMemberIdB(memberIdB);
        match.setMatchScore(BigDecimal.valueOf(score).setScale(2, java.math.RoundingMode.HALF_UP));
        match.setMatchType("MANUAL");
        match.setMatchStatus("MATCHED");
        match.setContactStatusA("PENDING");
        match.setContactStatusB("PENDING");
        match.setMatchResult("PENDING");
        match.setRemark(remark);
        // 自动填充字段：createTime、createBy、updateTime、updateBy、delFlag

        return datingMatchMapper.insert(match);
    }

    /**
     * 查询指定人员的匹配记录
     */
    @Override
    public List<DatingMatch> selectMatchByMemberId(Long memberId)
    {
        LambdaQueryWrapper<DatingMatch> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DatingMatch::getMemberIdA, memberId)
                   .or()
                   .eq(DatingMatch::getMemberIdB, memberId);
        return datingMatchMapper.selectList(queryWrapper);
    }

    /**
     * 统计匹配数据
     */
    @Override
    public Object getMatchStatistics()
    {
        Map<String, Object> stats = new HashMap<>();

        // 总匹配数
        DatingMatch query = new DatingMatch();
        List<DatingMatch> allMatches = datingMatchMapper.selectDatingMatchList(query);
        stats.put("totalMatches", allMatches.size());

        // 成功匹配数
        int successCount = datingMatchMapper.countSuccessMatch();
        stats.put("successMatches", successCount);

        // 成功率
        double successRate = allMatches.size() > 0 ? (double) successCount / allMatches.size() : 0.0;
        stats.put("successRate", String.format("%.2f%%", successRate * 100));

        // 各状态统计
        Map<String, Long> statusStats = allMatches.stream()
            .collect(Collectors.groupingBy(DatingMatch::getMatchStatus, Collectors.counting()));
        stats.put("statusStats", statusStats);

        return stats;
    }

    /**
     * 匹配候选人内部类
     */
    private static class MatchCandidate {
        private DatingMember member;
        private double score;

        public MatchCandidate(DatingMember member, double score) {
            this.member = member;
            this.score = score;
        }

        public DatingMember getMember() {
            return member;
        }

        public double getScore() {
            return score;
        }
    }
}
